package fragment

import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.DatePicker
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.viewModelScope
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.lifecycle.lifecycleOwner
import com.afollestad.materialdialogs.list.listItems
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.services.core.AMapException
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import com.emapp.lccode.R
import com.emapp.lccode.adapter.GridImageAdapter
import com.emapp.lccode.base.BaseConfig
import com.emapp.lccode.base.BaseFragment1
import com.emapp.lccode.base.EventBusConfig
import com.emapp.lccode.base.EventBusConfig.REFRESH_ADDRESS
import com.emapp.lccode.base.EventBusModel
import com.emapp.lccode.bean.DeviceKt
import com.emapp.lccode.bean.Field
import com.emapp.lccode.bean.SelectType
import com.emapp.lccode.bean.UpFileKt
import com.emapp.lccode.bean.UpLatLngKt
import com.emapp.lccode.databinding.FragmentProjectCompleteAddBinding
import com.emapp.lccode.databinding.LayoutInputBinding
import com.emapp.lccode.mode.ProjectDeviceViewModel
import com.emapp.lccode.utils.BaseUtil
import com.emapp.lccode.utils.DividerOrientation
import com.emapp.lccode.utils.GlideEngine
import com.emapp.lccode.utils.MmkvUtil
import com.emapp.lccode.utils.MyExternalPreviewEventListener
import com.emapp.lccode.utils.divider
import com.emapp.lccode.utils.getColorExt
import com.emapp.lccode.utils.getValueByPropertyName
import com.emapp.lccode.utils.grid
import com.emapp.lccode.utils.openGallery
import com.emapp.lccode.utils.setOnclickNoRepeat
import com.emapp.lccode.utils.statesList
import com.emapp.lccode.utils.toEntity
import com.emapp.lccode.utils.toJsonStr
import com.emapp.lccode.view.DeviceTypeDialog
import com.emapp.lccode.view.DistrictDialog
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.hjq.toast.Toaster
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.style.PictureSelectorStyle
import com.luck.picture.lib.utils.MediaUtils
import com.umeng.commonsdk.stateless.UMSLEnvelopeBuild
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import me.hgj.jetpackmvvm.ext.parseState
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.File
import java.util.Calendar


class ProjectCompleteAddKtFragment :
    BaseFragment1<ProjectDeviceViewModel, FragmentProjectCompleteAddBinding>(),
    AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener,
    DeviceTypeDialog.SelectTypeListener,
    DistrictDialog.SelectDistrictListener, DatePickerDialog.OnDateSetListener {

    var imageResult = arrayListOf<UpFileKt>()//上传图片返回结果
    private var mImages: ArrayList<LocalMedia> = arrayListOf()
    private val imageAdapter: GridImageAdapter by lazy {
        GridImageAdapter(
            requireContext(),
            mImages
        )
    }
    lateinit var launcherResult: ActivityResultLauncher<Intent>
    private lateinit var locationClient: AMapLocationClient
    private var latlng: UpLatLngKt? = null
//     var infor: DeviceKt=
    var infor: DeviceKt =DeviceKt("","","0","0","","",0,"")
    val geocoderSearch: GeocodeSearch by lazy { GeocodeSearch(requireContext()) }
    private var views: MutableList<LayoutInputBinding> = mutableListOf()//动态布局
    private lateinit var dynamicLayoutBinding: LayoutInputBinding
    val dynamicParams = mutableMapOf<String, String>()
    val dateDialog: DatePickerDialog by lazy {
        DatePickerDialog(
            requireActivity(), this, Calendar.getInstance()[Calendar.YEAR] //年份
            , Calendar.getInstance()[Calendar.MONTH] //月份
            , Calendar.getInstance()[Calendar.DAY_OF_MONTH]
        )
    }
    var dateDialogFlag = 1

    companion object {
        fun newInstance(status: String): ProjectCompleteAddKtFragment {
            val args = Bundle()
            args.putString("status", status)
            val fragment = ProjectCompleteAddKtFragment()
            fragment.arguments = args
            return fragment
        }
    }

    override fun initView(savedInstanceState: Bundle?) {
        EventBus.getDefault().register(this)
//        infor =
//            requireActivity().intent.getSerializableExtra("infor2") as DeviceKt? ?: DeviceKt()

        val inf = MmkvUtil.getString("infor1","")
        if (inf.isNotEmpty()){
            infor= inf.toEntity<DeviceKt>()!!
            //MmkvUtil.putString("infor1","")
        }
        mViewModel.project_id = requireActivity().intent.getStringExtra("project_id").toString()
        val project_name = requireActivity().intent.getStringExtra("project_name").toString()
        mViewBind.tvProject.text = project_name
        infor.project_id = mViewModel.project_id
        AMapLocationClient.updatePrivacyShow(activity, true, true)
        AMapLocationClient.updatePrivacyAgree(activity, true)
        geocoderSearch.setOnGeocodeSearchListener(this)
        launcherResult = createActivityResultLauncher()
        mViewBind.rvList.run {
            grid(4)
            adapter = imageAdapter
            divider {
                orientation = DividerOrientation.HORIZONTAL
                includeVisible = true
                setDivider(10, true)
                setColor(getColorExt(R.color.white))
            }
        }
        imageAdapter.run {
            selectMax = BaseConfig.selectMaxImage
            setOnItemClickListener(object : GridImageAdapter.OnItemClickListener {
                override fun onItemClick(v: View?, position: Int) {
                    PictureSelector.create(this@ProjectCompleteAddKtFragment)
                        .openPreview()
                        .setImageEngine(GlideEngine.createGlideEngine())
                        .setSelectorUIStyle(PictureSelectorStyle())
                        .isPreviewFullScreenMode(true)
                        .setExternalPreviewEventListener(MyExternalPreviewEventListener(this@run))
                        .startActivityPreview(position, true, data)
                }

                override fun openPicture() {
                    // 进入相册
                    openGallery(requireContext(), data, launcherResult)
                    // 单独拍照
                    // openCamera(requireContext(),data,launcherResult)
                }

            })
        }
        setInfor()
    }

    fun getWater(): String = infor.name + "\n" + infor.address + "\n" + infor.lng + "/" +
            infor.lat + "\n" + BaseUtil.getCurrentTime("yyyy-MM-dd HH:mm")

    /**
     * 懒加载
     */
    override fun lazyLoadData() {
    }

    @SuppressLint("SetTextI18n")
    fun setInfor() {
        infor.build_status = "3"
        mViewBind.lvOther.removeAllViews()
        views.clear()
        mViewModel.getDeviceField(infor.device_type)
        val tys = MmkvUtil.getTypes()
        tys?.let {
            for (i in tys) {
                if (infor.work_type == i.id) {
                    infor.work_type_name = i.itemLabel
                }
                if (infor.device_type == i.id) {
                    infor.device_type_name = i.itemLabel
                }
            }
        }
        mViewBind.run {
            tvName.setText(infor.name)
            tvNumCode.setText(infor.num_code)
            tvType.text = infor.work_type_name + "," + infor.device_type_name
            tvDistrict.text = infor.area_city
            tvStartDate.text = infor.star_time
            if (!infor.buildtime.isNullOrBlank())
                tvEndDate.text = infor.buildtime
            // tvRemark.setText(infor.remark)
        }
        if (!infor.lat.isNullOrBlank() && !infor.lng.isNullOrBlank() && infor.lng!!.toDoubleOrNull() != null) {
            latlng = UpLatLngKt(infor.lng!!.toDouble(), infor.lat!!.toDouble())
            latlng?.address = infor.address
            infor.upload_lnglat = "[" + latlng.toJsonStr() + "]"
            mViewBind.tvAddress.text = infor.lat + "/" + infor.lng
            mViewBind.tvAddress2.setText(infor.address)
        }
    }

    @SuppressLint("CheckResult")
    override fun createObserver() {

        mViewModel.run {
            file.observe(viewLifecycleOwner) { resultState ->
                parseState(resultState, {
                    imageResult.add(it)
                    if (mImages.isNotEmpty()) upFile()
                    else {
                        dismissLoading()
                        add()
                    }
                }, {
                    Toaster.show(it.errorMsg)
                })
            }
            deviceAdd.observe(viewLifecycleOwner) { resultState ->
                parseState(resultState, {
                    Toaster.show("提交成功")
                    EventBus.getDefault().post(EventBusModel(EventBusConfig.REFRESH_PROJECT_DEVICE))
                    viewModelScope.launch {
                        delay(500)
                        activity?.finish()
                    }
                }, {
                    Toaster.show(it.errorMsg)
                })
            }
            fields.observe(viewLifecycleOwner) { resultState ->
                parseState(resultState, {
                    for ((indext, i) in it.withIndex()) {
                        dynamicLayoutBinding =
                            LayoutInputBinding.inflate(layoutInflater, null, false)
                        when (i.field_type) {
                            "select" -> {
                                dynamicLayoutBinding.apply {
                                    lvType.visibility = View.VISIBLE
                                    lvInput.visibility = View.GONE
                                    tvTypeName.text = i.name
                                    tvType.text =
                                        getValueByPropertyName(infor, i.field_name).toString()
                                    tvType.setOnClickListener { buttonView ->
                                        MaterialDialog(requireContext()).show {
                                            cancelable(true)
                                            lifecycleOwner(viewLifecycleOwner)
                                            listItems(null, i.list) { v, index, text ->
                                                val clickedViewBinding =
                                                    views.find { it.root == buttonView.parent.parent }
                                                clickedViewBinding?.tvType?.text = text
                                            }
                                        }
                                    }
                                }
                            }

                            else -> {
                                dynamicLayoutBinding.apply {
                                    lvType.visibility = View.GONE
                                    lvInput.visibility = View.VISIBLE
                                    tvInName.text = i.name
                                    tvInput.setText(
                                        getValueByPropertyName(
                                            infor,
                                            i.field_name
                                        ).toString()
                                    )
                                }
                            }
                        }
                        dynamicLayoutBinding.line.visibility =
                            if (indext == it.size - 1) {
                                View.GONE
                            } else {
                                View.VISIBLE
                            }
                        mViewBind.lvOther.addView(dynamicLayoutBinding.root)
                        dynamicLayoutBinding.root.tag = i
                        views.add(dynamicLayoutBinding)
                    }
                }, {
                    Toaster.show(it.errorMsg)
                })
            }
        }

    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onEventMainThread(event: EventBusModel) {
        when (event.type) {
            REFRESH_ADDRESS -> {}
            else -> {}
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        EventBus.getDefault().unregister(this)
        destroyLocation()
    }

    @SuppressLint("CheckResult")
    override fun onBindViewClick() {
        setOnclickNoRepeat(
            mViewBind.tvAddress,
            mViewBind.tvProject,
            mViewBind.btOk,
            mViewBind.tvDistrict,
            mViewBind.tvStartDate,
            mViewBind.tvEndDate,
            mViewBind.tvType
        ) {
            when (it.id) {
                R.id.tv_state -> {
                    MaterialDialog(requireContext()).show {
                        cancelable(true)
                        lifecycleOwner(viewLifecycleOwner)
                        listItems(null, statesList) { v, index, text ->
                            mViewBind.tvState.text = text
                            infor.build_status = if (text == "未开工") "1" else "2"
                        }
                    }
                }

                R.id.tv_address -> {
                    XXPermissions.with(this)
                        .permission(Permission.ACCESS_COARSE_LOCATION)
                        .permission(Permission.ACCESS_FINE_LOCATION)
                        .permission(Permission.READ_PHONE_STATE)
                        .request(object : OnPermissionCallback {
                            override fun onGranted(permissions: List<String>, all: Boolean) {
                                initLocation()
                            }

                            override fun onDenied(permissions: List<String>, never: Boolean) {}
                        })

                }


                R.id.tv_start_date -> {
                    dateDialogFlag = 1
                    dateDialog.show()
                }

                R.id.tv_end_date -> {
                    dateDialogFlag = 2
                    dateDialog.show()
                }

                R.id.tv_type -> {
                    mViewModel.typeDialog.listener = this
                    mViewModel.typeDialog.selectType = mViewModel.selectType
                    mViewModel.typeDialog.show(requireActivity())
                }

                R.id.tv_district -> {
                    mViewModel.districtDialog.listener = this
                    mViewModel.districtDialog.selectType = mViewModel.selectDistrict
                    mViewModel.districtDialog.show(requireActivity())
                }

                R.id.bt_ok -> {
                    val name = mViewBind.tvName.text.toString().trim().trimEnd()
                    if (name.isNullOrBlank()) {
                        Toaster.show("请输入单体名称")
                        return@setOnclickNoRepeat
                    }
                    infor.name = name
                    val num_code = mViewBind.tvNumCode.text.toString().trim().trimEnd()
                    if (num_code.isNullOrBlank()) {
                        Toaster.show("请输入工程编号")
                        return@setOnclickNoRepeat
                    }
                    infor.num_code = num_code
                    if (infor.work_type.isNullOrBlank()) {
                        Toaster.show("请选择设备分类")
                        return@setOnclickNoRepeat
                    }
                    if (infor.device_type.isNullOrBlank()) {
                        Toaster.show("请选择设备分类子类")
                        return@setOnclickNoRepeat
                    }
                    if (infor.city.isNullOrBlank()) {
                        Toaster.show("请选择所在乡镇")
                        return@setOnclickNoRepeat
                    }
                    if (infor.upload_lnglat.isNullOrBlank()) {
                        Toaster.show("请设置设备所在位置")
                        return@setOnclickNoRepeat
                    }
                    val star_time = mViewBind.tvStartDate.text.toString().trimEnd()
                    if (star_time.isNullOrBlank()) {
                        Toaster.show("请设置开工日期")
                        return@setOnclickNoRepeat
                    }
                    infor.star_time = star_time
                    val end_time = mViewBind.tvEndDate.text.toString().trimEnd()
                    if (end_time.isNullOrBlank()) {
                        Toaster.show("请设置竣工日期")
                        return@setOnclickNoRepeat
                    }
                    infor.buildtime = end_time
                    val remark = mViewBind.tvRemark.text.toString().trimEnd()
                    infor.remark = remark
                    // 动态创建参数 Map
                    dynamicParams.clear()
                    views.forEach { it ->
                        val data: Field = it.root.tag as Field
                        if (data.field_type == "select") {
                            data.value = it.tvType.text.toString().trim().trimEnd()
                        } else {
                            data.value = it.tvInput.text.toString().trim().trimEnd()
                        }
                        dynamicParams[data.field_name] = data.value
                    }
                    mImages.clear()
                    mImages.addAll(imageAdapter.data)
                    imageResult.clear()
                    if (mImages.isNotEmpty()) {
                        showLoading("正在上传图片")
                        upFile()
                    } else {
                        add()
                    }
                }
            }
        }
    }

    private fun add() {
        infor.file_ids = imageResult.joinToString(",") { file -> file.id }
        mViewModel.updateDevice(infor, dynamicParams)
    }

    private fun upFile() {
        if (!mImages[0].availablePath.isNullOrBlank()) {
            val file = File(mImages[0].availablePath)
            mViewModel.upFileComplete(file)
            mImages.removeAt(0)
        } else {
            mImages.removeAt(0)
            if (mImages.isNotEmpty()) upFile()
            else {
                dismissLoading()
                add()
            }
        }
    }

    private fun initLocation() {
        showLoading("定位中")
        locationClient = AMapLocationClient(activity).apply {
            setLocationOption(getDefaultOption())
            setLocationListener(this@ProjectCompleteAddKtFragment)
            startLocation()
        }
    }

    private fun getDefaultOption(): AMapLocationClientOption {
        val mOption = AMapLocationClientOption().apply {
            locationMode =
                AMapLocationClientOption.AMapLocationMode.Hight_Accuracy //可选，设置定位模式，可选的模式有高精度、仅设备、仅网络。默认为高精度模式
            isOnceLocation = true
            isLocationCacheEnable = true //可选，设置是否使用缓存定位，默认为true
        }
        return mOption
    }


    private fun stopLocation() {
        locationClient.stopLocation()
    }

    private fun destroyLocation() {
        if (::locationClient.isInitialized) {
            locationClient.onDestroy()
        }
    }

    override fun onLocationChanged(location: AMapLocation?) {
        dismissLoading()
        if (null != location) {
            if (location.errorCode == 0) {
                MmkvUtil.putString("lng", "" + location.longitude)
                MmkvUtil.putString("lat", "" + location.latitude)
                latlng = UpLatLngKt(location.longitude, location.latitude)
                if (location.address.isNullOrBlank()) {
                    val point = LatLonPoint(location.latitude, location.longitude)
                    showLoading("定位中...")
                    getAddress(point)
                } else {
                    mViewBind.tvAddress2.setText(location.address)
                    infor.address = location.address
                    latlng?.address = location.address
                }
                mViewBind.tvAddress.text =
                    location.longitude.toString() + "/" + location.latitude
                infor.upload_lnglat = "[" + latlng.toJsonStr() + "]"
            } else {
                log_e("定位失败错误码:${location.errorCode}\n")
                log_e("错误信息:${location.errorInfo}\n")
                log_e("错误描述:${location.locationDetail}\n")
            }
        } else {
            log_e("定位失败，loc is null")
        }
        stopLocation()
    }

    private fun createActivityResultLauncher(): ActivityResultLauncher<Intent> {
        return registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) { result ->
            val resultCode = result.resultCode
            if (resultCode == AppCompatActivity.RESULT_OK) {
                val selectList = PictureSelector.obtainSelectorList(result.data)
                analyticalSelectResults(selectList)
            } else if (resultCode == AppCompatActivity.RESULT_CANCELED) {
                Log.i(TAG, "onActivityResult PictureSelector Cancel")
            }
        }
    }

    private fun analyticalSelectResults(result: java.util.ArrayList<LocalMedia>) {
        for (media in result) {
            if (media.width == 0 || media.height == 0) {
                if (PictureMimeType.isHasImage(media.mimeType)) {
                    val imageExtraInfo =
                        MediaUtils.getImageSize(UMSLEnvelopeBuild.mContext, media.path)
                    media.width = imageExtraInfo.width
                    media.height = imageExtraInfo.height
                } else if (PictureMimeType.isHasVideo(media.mimeType)) {
                    val videoExtraInfo =
                        MediaUtils.getVideoSize(UMSLEnvelopeBuild.mContext, media.path)
                    media.width = videoExtraInfo.width
                    media.height = videoExtraInfo.height
                }
            }
        }
        val isMaxSize = result.size == imageAdapter.selectMax
        val oldSize: Int = imageAdapter.data.size
        imageAdapter.notifyItemRangeRemoved(0, if (isMaxSize) oldSize + 1 else oldSize)
        imageAdapter.data.clear()
        imageAdapter.data.addAll(result)
        imageAdapter.notifyItemRangeInserted(0, result.size)
    }

    override fun onRegeocodeSearched(result: RegeocodeResult?, resultCode: Int) {
        dismissLoading()
        if (resultCode == AMapException.CODE_AMAP_SUCCESS && result != null) {
            mViewBind.tvAddress2.setText(result.regeocodeAddress?.formatAddress)
            infor.address = mViewBind.tvAddress2.text.toString()
            latlng?.address = mViewBind.tvAddress2.text.toString()
            infor.upload_lnglat = "[" + latlng.toJsonStr() + "]"
        }
    }

    override fun onGeocodeSearched(p0: GeocodeResult?, p1: Int) {
    }

    override fun onSelectTypeComplete(type: SelectType) {
        mViewModel.selectType = type
        infor.work_type = type.id0
        infor.device_type = type.device_type
        mViewBind.tvType.text = type.name0 + "," + type.device_type_name
        mViewBind.lvOther.removeAllViews()
        views.clear()
        if (infor.device_type.isEmpty()) {
            Toaster.show("请选择二级分类")
        } else {
            mViewModel.getDeviceField(infor.device_type)
        }
    }

    override fun onSelectDistrictComplete(type: SelectType) {
        mViewModel.selectDistrict = type
        infor.province = type.id0
        infor.city = type.id1
        infor.district = type.id2
        var s = ""
        if (type.name2.isNotEmpty())
            s = type.name2
        else if (type.name1.isNotEmpty())
            s = type.name1
        else if (type.name0.isNotEmpty())
            s = type.name0
        mViewBind.tvDistrict.text = s
    }

    override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
        val desc = String.format("%s-%02d-%02d", year, month + 1, dayOfMonth)
        if (dateDialogFlag == 1)
            mViewBind.tvStartDate.text = desc
        else
            mViewBind.tvEndDate.text = desc
    }

    fun getAddress(latLonPoint: LatLonPoint?) {

        val query = RegeocodeQuery(
            latLonPoint, 200f,
            GeocodeSearch.AMAP
        ) // 第一个参数表示一个Latlng，第二参数表示范围多少米，第三个参数表示是火系坐标系还是GPS原生坐标系
        geocoderSearch.getFromLocationAsyn(query) // 设置异步逆地理编码请求
    }


}